/*
 * Created on Feb 15, 2005
 *
 * The Monterey Bay Aquarium Research Institute (MBARI) provides this
 * documentation and code 'as is', with no warranty, express or
 * implied, of its quality or consistency. It is provided without support and
 * without obligation on the part of MBARI to assist in its use, correction,
 * modification, or enhancement. This information should not be published or
 * distributed to third parties without specific written permission from MBARI
 */


package org.mbari.vcr;

import java.io.IOException;
import java.util.Date;
import org.mbari.comm.BadPortException;
import org.mbari.util.IObserver;
import org.mbari.util.NumberUtil;
import org.mbari.vcr.IVCR;
import org.mbari.vcr.rs422.VCR;
import org.mbari.vcr.rs422.VCRReply;
import org.mbari.vcr.rs422.VCRTimecode;
import org.mbari.vcr.rs422.VCRUserbits;

/**
 * @author brian
 * @version $Id: WriteUserbitsTest.java 132 2006-01-10 19:52:44Z hohonuuli $
 */
public class WriteUserbitsDemo {

    private IVCR vcr;

    /**
     *
     * @param port
     * @throws BadPortException
     * @throws IOException
     *
     */
    public WriteUserbitsDemo(String port) throws IOException, BadPortException {
        super();
        vcr = new VCR(port);

        //vcr = new VCRAdapter();

        //vcr = new SonyVCRProxy(port);
        vcr.getVcrReply().addObserver(new ReplyObserver());
        vcr.getVcrUserbits().addObserver(new UserbitObserver());
        vcr.getVcrTimecode().addObserver(new TimecodeObserver());

    }

    /**
     * Method description
     *
     *
     * @throws InterruptedException
     */
    public void run() throws InterruptedException {

        System.out.println();
        printCommand("STOP            ", VCR.STOP);
        printCommand("GET_STATUS      ", VCR.GET_STATUS);
        vcr.stop();
        Thread.sleep(1000);

        System.out.println();
        printCommand("RECORD          ", VCR.RECORD);
        printCommand("GET_STATUS      ", VCR.GET_STATUS);
        vcr.record();
        Thread.sleep(5000);

        /*
         * System.out.println();
         * byte[] b=
         * printCommand("PRESET_TIMECODE ", VCRProxy.PRESET_TIMECODE);
         *       vcr.presetTimecode(new byte[] { VCRUtil.intToTime(1), VCRUtil.intToTime(2),
         *                       VCRUtil.intToTime(3), VCRUtil.intToTime(4)});
         */

        System.out.println();
        printCommand("GET_TIMECODE    ", VCR.GET_TIMECODE);
        vcr.requestTimeCode();
        Thread.sleep(50);

        System.out.println();
        printCommand("GET_VTIMECODE   ", VCR.GET_VTIMECODE);
        vcr.requestVTimeCode();
        Thread.sleep(50);

        System.out.println();
        printCommand("GET_LTIMECODE   ", VCR.GET_LTIMECODE);
        vcr.requestLTimeCode();
        Thread.sleep(50);

        /*
         * We're writing to the userbits in this loop
         */
        byte[] cmd = VCR.PRESET_USERBITS;

        for (int i = 0; i < 6; i++) {
            Date d = new Date();
            int t = (int) (d.getTime() / 1000);

            byte[] b = NumberUtil.toByteArray(t, true);
            System.out.println();
            String ts = "! Current Time is " + t + "(secs) little endian bytes = ";
            System.out.print(ts);
            printByteArray(b);
            System.out.println();

            for (int j = 0; j < b.length; j++) {
                cmd[j + 2] = b[j];
            }

            printCommand("PRESET_USERBITS ", cmd);
            printCommand("GET_STATUS      ", VCR.GET_STATUS);
            vcr.presetUserbits(b);
            Thread.sleep(200);

            System.out.println();
            printCommand("GET_VUBTIMECODE ", VCR.GET_VUBTIMECODE);
            vcr.requestVUserbits();
            Thread.sleep(200);

            System.out.println();
            printCommand("GET_LUBTIMECODE ", VCR.GET_LUBTIMECODE);
            vcr.requestLUserbits();
            Thread.sleep(200);

            System.out.println();
            printCommand("GET_TIMECODE    ", VCR.GET_TIMECODE);
            vcr.requestTimeCode();
            Thread.sleep(700);

        }

        System.out.println();
        printCommand("STOP            ", VCR.STOP);
        printCommand("GET_STATUS      ", VCR.GET_STATUS);
        vcr.stop();
        Thread.sleep(1000);

        System.out.println();
        System.out.println("! Closing the serial port");
        vcr.disconnect();
    }

    /**
     * Method description
     *
     *
     * @param args
     */
    public static void main(String[] args) {

        if (args.length != 1) {
            System.out.println("Use as: WriteUserbitsTest [serialport]");
            System.exit(-1);
        }

        try {
            WriteUserbitsDemo test = new WriteUserbitsDemo(args[0]);
            test.run();
        }
        catch (IOException e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (BadPortException e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (InterruptedException e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (Exception e) {
            e.printStackTrace();
        }


    }

    private static void printByteArray(byte[] b) {
        System.out.print("[");

        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString((int) b[i]);

            if (hex.length() == 1) {
                hex = "0" + hex;
            }

            if (hex.length() > 2) {
                hex = hex.substring(hex.length() - 2);
            }

            System.out.print("0x" + hex);

            if (i < b.length - 1) {
                System.out.print(", ");
            }
        }

        System.out.print("]");
    }

    private static void printCommand(String msg, byte[] cmd) {
        System.out.print("--> " + msg + " ");
        printByteArray(cmd);
        System.out.println();
    }

    private class ReplyObserver implements IObserver {

        /**
         * Method description
         *
         *
         * @param obj
         * @param changeCode
         */
        public void update(Object obj, Object changeCode) {
            VCRReply r = (VCRReply) obj;
            byte[] cmd = r.getCmd();
            byte[] data = r.getData();
            byte[] chk = r.getChecksum();
            int length = cmd.length + chk.length;
            if (data != null) {
                length += data.length;
            }

            byte[] b = new byte[length];
            System.arraycopy(cmd, 0, b, 0, cmd.length);
            int chkStart = cmd.length;
            if (data != null) {
                System.arraycopy(data, 0, b, cmd.length, data.length);
                chkStart += data.length;
            }

            System.arraycopy(chk, 0, b, chkStart, chk.length);
            System.out.print("<-- ");
            printByteArray(b);
            System.out.print(" response to command of ");
            printByteArray(r.getCommand());
            System.out.println();
        }
    }

    private class TimecodeObserver implements IObserver {

        /**
         * Method description
         *
         *
         * @param obj
         * @param changeCode
         */
        public void update(Object obj, Object changeCode) {
            VCRTimecode tc = (VCRTimecode) obj;
            System.out.println("! Timecode is " + tc.toString());

        }
    }

    private class UserbitObserver implements IObserver {

        /**
         * Method description
         *
         *
         * @param obj
         * @param changeCode
         */
        public void update(Object obj, Object changeCode) {
            VCRUserbits ub = (VCRUserbits) obj;
            long t = ((long) NumberUtil.toInt(ub.getUserbits(), true));
            Date d = new Date(t);
            System.out.println("! Userbits time is " + t + "(secs) [" + d + "]");
        }
    }
}
